package com.itmuch.contentcenter;


import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.itmuch.contentcenter.dao.content.ShareMapper;
import com.itmuch.contentcenter.domain.dto.user.UserDto;
import com.itmuch.contentcenter.domain.entity.content.Share;
import com.itmuch.contentcenter.feignclient.TestBaiduFeignClient;
import com.itmuch.contentcenter.feignclient.TestUserCenterFeignClient;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author caiqian
 * @date 2021/5/6 14:38
 */
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class TestController {


  private final ShareMapper shareMapper;

  private final DiscoveryClient discoveryClient;

  @GetMapping("/test")
  public List<Share> testInsert() {
    //1 insert
    Share share = new Share();
    share.setCreateTime(new Date());
    share.setUpdateTime(new Date());
    share.setTitle("xxx");
    share.setCover("fff");
    share.setAuthor("cai");
    share.setBuyCount(1);

    shareMapper.insertSelective(share);

    //2 query
    List<Share> shareList = shareMapper.selectAll();

    return shareList;
  }

  @GetMapping("/test2")
  public List<ServiceInstance> getInstances() {
    //查询指定服务的所有信息
    return this.discoveryClient.getInstances("user-center");
  }

  @Autowired
  private TestUserCenterFeignClient testUserCenterFeignClient;

  @GetMapping("/test-get")
  public UserDto query(UserDto userDto) {
    return this.testUserCenterFeignClient.query(userDto);
  }

  @Autowired
  private TestBaiduFeignClient testBaiduFeignClient;

  @GetMapping("/baidu")
  public String baiduIndex() {
    return this.testBaiduFeignClient.index();
  }

  @Autowired
  private TestService testService;

  @GetMapping("/test-a")
  public String testA() {
    this.testService.common();
    return "test-a";
  }

  @GetMapping("/test-b")
  public String testB() {

    this.testService.common();
    return "test-b";
  }

  @GetMapping("/test-add-flow-rule")
  public String testHot() {

    this.initFlowQpsRule();
    return "Successfully!";
  }

  private void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule("/shares/1");
// set limit qps to 20
    rule.setCount(20);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setLimitApp("default");
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
  }

  @GetMapping("/test-sentinel-api")
  public String testSentinelApi(
      @RequestParam(required = false) String a
  ) {

    String resourceName = "test-sentinel-api";
    ContextUtil.enter(resourceName, "test-wfw");

    Entry entry = null;

    try {
      //定义一个Sentinel保护的资源,名称是test-sentinel-api
      entry = SphU.entry(resourceName);

      if (StringUtils.isBlank(a)) {
        throw new IllegalArgumentException("a不能为空!");
      }

      return a;
    }
    //如果被保护的资源限流或者降级了,就会触发BlockException
    catch (BlockException e) {
      log.warn("限流或者降级了!", e);
      e.printStackTrace();
      return "限流或者降级了!";
    } catch (IllegalArgumentException e2) {
      //统计IllegalArgumentException
      Tracer.trace(e2);
      return "没有提供参数!";
    } finally {
      if (entry != null) {
        //退出entry
        entry.exit();
      }

      ContextUtil.exit();
    }
  }

  @GetMapping("/test-sentinel-resouorce")
  @SentinelResource(value = "test-sentinel-api",
      blockHandler ="block",
      blockHandlerClass = TestControllerBlockerHandleClass.class
      ,fallback = "fallback")
  public String testSentinelResource(
      @RequestParam(required = false) String a
  ) {
    if (StringUtils.isBlank(a)) {
      throw new IllegalArgumentException("a cannot be blank!");
    }
    //      entry = SphU.entry(resourceName);
      return a;
  }

  public String block(String a, BlockException e) {
    log.warn("block!", e);
    return "block!";
  }

  public String fallback(String a) {
    log.warn("fallback!");
    return "fallback!";
  }

  @Autowired
  private RestTemplate restTemplate;
  @GetMapping("test-rest-template-sentinel/{userid}")
  public UserDto test(@PathVariable Integer userid){
    return this.restTemplate.getForObject(
        "http://user-center/users/{userid}",
        UserDto.class,
        userid);
  }

  @Autowired
  private Source source;

  @GetMapping("test-stream")
  public String testStream(){
    this.source.output().send(
        MessageBuilder.withPayload("消息体").build()
    );

    return "success";
  }
}
